package com.disgruntledbots;

import java.util.ArrayList;

import org.andengine.engine.handler.IUpdateHandler;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.badlogic.gdx.physics.box2d.Body;

import android.util.Log;

public class RecorderUpdateHandler implements IUpdateHandler {

	PhysicsEntityConnector projectile;
	ArrayList<PhysicsEntityConnector> mObjects;
	
	JSONObject jsonObj;
	MultiplayerActivity mParent;
	
	boolean recording;
	boolean postCollision;
	int step;
	int recordingStart;
	int recordingStop;
	int recordingTime;
	
	public RecorderUpdateHandler(ArrayList<PhysicsEntityConnector> objects, MultiplayerActivity parent)
	{
		step = 0;
		this.mObjects = objects;
		recording = false;
		projectile = null;
		
		jsonObj = new JSONObject();
		mParent = parent;
		try {
			jsonObj.putOpt("Initial", objects.toArray());
		} catch (JSONException e) {
			Log.e("RecodUpdateHandler", "JSON Exception: Initial", e);
		}
	}
	
	@Override
	public void onUpdate(float pSecondsElapsed) {
		
		if(recording){
			if(recordingTime % 3 == 0)
			{
				ArrayList<PhysicsEntityConnector> movingBodies = new ArrayList<PhysicsEntityConnector>();
				for(PhysicsEntityConnector o : this.mObjects)
				{
					if(o != null){
						if(o.mBody.isAwake())
						{
							movingBodies.add(o);
						}
					}
				}
				if(!movingBodies.isEmpty())
				{
					JSONArray jarray = new JSONArray();
					
					for(PhysicsEntityConnector b : movingBodies){
						try {
							jarray.put(PhysicsJSONSerializer.SerializeBody(b.mBody, b.name));
						} catch (JSONException e) {
							Log.e("RecorderUpdateHandler", "JSON Exception: Serializing", e);
						}	catch(ClassCastException e){
							Log.e("RecorderUpdateHandler", "JSON Exception: ClassCast", e);
						}
					}
					
					try {
						this.jsonObj.put("Step:" + this.recordingTime, jarray);
					} catch (JSONException e) {
						Log.e("RecorderUpdateHandler", "JSON Exception: Recoding " + recordingTime, e);
					}
				
				}else{
					recording = false;
				}
			}
			
			if(recordingTime == 300)
			{
				this.StopRecording();
			}
		}
		recordingTime++;
		step++;
	}

	@Override
	public void reset() {
		step = 0;
		recording = false;
		projectile = null;
		
		jsonObj = new JSONObject();
		
		
		try {
			jsonObj.putOpt("Initial State", this.mObjects.toArray());
		} catch (JSONException e) {
			Log.e("RecodUpdateHandler", "JSON Exception: Initial", e);
		}

		mObjects.trimToSize();
	}
	
	public void registerProjectile(PhysicsEntityConnector projectile)
	{
		this.projectile = projectile;
		try {
			jsonObj.putOpt("Fire", projectile.mBody);
		} catch (JSONException e) {
			Log.e("RecodUpdateHandler", "JSON Exception: Register", e);
		}
	}
	
	public void unRegisterProjectile()
	{
		if(projectile != null){
			if(projectile.mBody != null){
				projectile.dispose();
			}
		}
		this.projectile = null;
	}
	
	public void startRecording(PhysicsEntityConnector projectile)
	{
		this.reset();
		recording = true;
		recordingTime = 0;
		recordingStart = step;
		this.registerProjectile(projectile);
	}
	
	public JSONObject getJSON()
	{
		JSONObject object = new JSONObject();
		try {
			object.put("Turn Data", jsonObj);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return object;
	}
	
	public void StopRecording()
	{
		JSONArray jarray = new JSONArray();
		
		this.unRegisterProjectile();
		
		recording = false;
		for(PhysicsEntityConnector o : mObjects)
		{
			try{
				if(o != null){
					if(o.mBody != null){
						o.mBody.setLinearVelocity(0, 0);
						o.mBody.setAngularVelocity(0);
						try {
							jarray.put(PhysicsJSONSerializer.SerializeBody(o.mBody, o.name));
						} catch (ClassCastException e) {
							Log.e("RecordUpdateHandler", "JSONArray Class Cast");
						} catch (JSONException e) {
							Log.e("RecordUpdateHandler", "JSONArray Exception");
						} 
					}
				}
			}catch(NullPointerException e)
			{
				Log.e("Stop Recording", "NULL Exception Caught", e);
			}
		}
		
		try {
			this.jsonObj.put("Step: Final", jarray);
		} catch (JSONException e) {
			Log.e("RecordUpdateHandler", "JSONObject Exception");
		}
		
		mParent.turnFinished();
		this.reset();
	}
}
